package com.fbs.wowo.finance.service.imp;

import com.alibaba.fastjson.JSONObject;
import com.fbs.wowo.exception.CreateEntityFailedException;
import com.fbs.wowo.exception.ErrorCode;
import com.fbs.wowo.exception.NoSuchDataException;
import com.fbs.wowo.finance.service.CashService;
import com.fbs.wowo.finance.util.BillGenerator;
import com.fbs.wowo.finance.util.HttpUtils;
import com.fbs.wowo.finance.util.MathUtils;
import com.fbs.wowo.manage.entity.AccountDetail;
import com.fbs.wowo.manage.mapper.AccountDetailMapper;
import com.fbs.wowo.manage.service.AccountService;
import com.fbs.wowo.manage.vo.NamePassVo;
import com.fbs.wowo.util.common.Constants;
import com.fbs.wowo.util.common.Validator;
import com.github.wxpay.sdk.WXOpenConfig;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.github.wxpay.sdk.WXPubConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Service("cashService")
@Transactional
public class CashServiceImp implements CashService {
    public static final String WX_Redirect_uri = Constants.getURL() + "/cash/wxauth";
    public static final String WX_SCOPE = "snsapi_base";
    public static final String AUTH =
            "https://open.weixin.qq.com/connect/oauth2/authorize?" +
                    "appid=" + WXPubConfig.WX_PAY_APP_ID +
                    "&redirect_uri=" + WX_Redirect_uri +
                    "&response_type=code" +
                    "&scope=" + WX_SCOPE +
                    "&state=" + "%1$s" +
                    "#wechat_redirect";

    @Override
    public String wxPreAuthUrl(String userId, OutputStream outputStream) throws CreateEntityFailedException {
        Validator.verifyStr(userId);
        // TODO userId在不在
        String url = String.format(AUTH, userId);
//        try {
//            QrCodeUtils.writeToStream(url, outputStream, 300, 300);
//        } catch (WriterException e) {
//            e.printStackTrace();
//            throw new CreateEntityFailedException(e.getMessage());
//        } catch (IOException e) {
//            e.printStackTrace();
//            throw new CreateEntityFailedException(e.getMessage());
//        }
        return url;
    }

    /**
     * 绑定微信号
     * @param code
     * @param userId
     */
    public static final String OPENID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
            "appid=" + WXOpenConfig.WX_PAY_APP_ID +
            "&secret=" + WXOpenConfig.WX_AppSecret +
            "&code=" + "%1$s" +
            "&grant_type=authorization_code";
    @Override
    public void wxAuth(String code, String userId) throws NoSuchDataException {
        Validator.verifyStr(code);
        Validator.verifyStr(userId);
        String openid = null;
        String url = String.format(OPENID_URL, code);

        try {
            String post = HttpUtils.post(url);
            System.out.println(post);
            JSONObject jo = JSONObject.parseObject(post);
            openid = jo.getString("openid");
            if (!StringUtils.hasText(openid)) {
                String errcode = jo.getString("errcode");
                String errmsg = jo.getString("errmsg");
                if (StringUtils.hasText(errcode)) {
                    throw new NoSuchDataException("errcode: " + errcode + "errmsg: " + errmsg + "/nURL: " + post);
                }
                throw new NoSuchDataException("获取openid失败" + "/nURL: " + post);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new NoSuchDataException("获取openid失败:" + e.getMessage());
        }

        AccountDetail ad = accountDetailMapper.findByUserId(userId);
        if (ad == null) throw new NoSuchDataException(ErrorCode.ERR_ACCOUNT_NULL);
        AccountDetail accountDetail = new AccountDetail();
        accountDetail.setId(ad.getId());
        accountDetail.setWxOpenId(openid);
        accountDetailMapper.updateByPrimaryKeySelective(accountDetail);
    }

    // 提现api
    // "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"
    public static final String CASH_URL = "/mmpaymkttransfers/promotion/transfers";
    // 全使用公众号的
    public static final String check_name = "NO_CHECK";

    /**
     * 提现
     *
     * @param ip
     * @param userId
     * @param password
     * @param fee
     * @throws NoSuchDataException
     */
    @Override
    public void wxCash(String ip, String userId, String password, BigDecimal fee) throws NoSuchDataException {
        NamePassVo namePassVo = new NamePassVo();
        namePassVo.setUserId(userId);
        namePassVo.setPassword(password);
        accountService.verifyPass(namePassVo);
        wxCash(ip, userId, fee);
    }

    @Override
    public void wxCash(String ip, String userId, BigDecimal fee) throws NoSuchDataException {
        // 验证
        Validator.verifyStr(ip);
        Validator.verifyStr(userId);
        Validator.verifyNon(fee);

        /*
         * 实名认证
         * 绑定微信
         * 交易密码
         */
//        WXPubConfig config = new WXPubConfig();
        WXOpenConfig config = new WXOpenConfig();
        // 数据初始化
        AccountDetail ad = accountDetailMapper.findByUserId(userId);
        if (ad == null) throw new NoSuchDataException(ErrorCode.ERR_CERT_NULL);
        String openid = ad.getWxOpenId();
        if (!StringUtils.hasText(openid)) throw new NoSuchDataException(ErrorCode.ERR_PAY_WX_BIND);
        String tradeId = BillGenerator.tradeId((byte) 1, BillGenerator.TradeType.PayWXCash.getKey(), BillGenerator.ProCt.WXCASH.getKey(), BillGenerator.ProT.CASH.getKey());
        int amount = MathUtils.parseYuanToFen(fee);
        String scene = BillGenerator.genScene("提现", BillGenerator.ProT.CASH.getKey(), BillGenerator.ProCt.WXCASH.getKey(), BillGenerator.Income_Outcome);

        // 参数map
        Map<String, String> data = new HashMap<>();
        data.put("mch_appid", config.getAppID());
        data.put("mchid", config.getMchID());
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("partner_trade_no", tradeId);
        data.put("openid", openid);
        data.put("check_name", check_name);
        data.put("amount", amount + "");
        data.put("desc", scene);
        data.put("spbill_create_ip", ip);
        try {
            data.put("sign", WXPayUtil.generateSignature(data, config.getKey()));
        } catch (Exception e) {
            e.printStackTrace();
            throw new CreateEntityFailedException("签名失败");
        }

        // 签名xml
        // 发送
        WXPay pay = new WXPay(config);
        try {
            String resultXml = pay.requestWithCert(CASH_URL, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs());
            Map<String, String> map = WXPayUtil.xmlToMap(resultXml);
            if ("FAIL".equals(map.get("return_code")))
                throw new CreateEntityFailedException(map.get("return_msg"));
            if ("FAIL".equals(map.get("result_code")))
                throw new CreateEntityFailedException(map.get("err_code") + " : " + map.get("err_code_des"));
        } catch (Exception e) {
            e.printStackTrace();
            throw new CreateEntityFailedException(e.getMessage());
        }
    }

    /**
     * 账号是否绑定过微信
     *
     * @param userId
     * @return
     */
    @Override
    public int hasBindWX(String userId) {
        Validator.verifyStr(userId);
        AccountDetail ad = accountDetailMapper.findByUserId(userId);
        if (ad == null) throw new CreateEntityFailedException(ErrorCode.ERR_ACCOUNT_NULL);
        if (StringUtils.hasText(ad.getWxOpenId()))
            return 1;
        else
            return 0;
    }

    @Autowired
    private AccountDetailMapper accountDetailMapper;
    @Autowired
    private AccountService accountService;
}
